/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gaib.dmc;

import static com.gaib.dmc.AODEsrReviewer.LoadModel;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import weka.classifiers.Classifier;
import weka.classifiers.UpdateableClassifier;
import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;

/**
 *
 * @author Ahmad Fauzan
 */
public class NaiveBayesReviewer implements Reviewer{
    final String modelPath = "naive-update.model";
    final String atributHeader = "header_bayes";
    Classifier cls;
    Instances dataInstances;
    List<Instance> dataSet;
    
    String cbStep = "";
    String cSession = "";
    double cDuration = 0;
    String cbCount = "";
    double ccCount = 0;
    double transact_n = 0;
    
    //Atributes
    FastVector atts;
    
    public NaiveBayesReviewer() {
        cls = LoadModel(modelPath);
        try { 
            SetUpAttribures(atributHeader);
        } catch (IOException ex) {
            System.out.println(ex.toString());
        }
    }

    private void SetUpAttribures(String atributHeader) throws IOException {
        System.out.println("SetUpAtributes");
        atts = new FastVector();
        InputStream is = NaiveBayesReviewer.class.getResourceAsStream(atributHeader);
        int c = is.read();
        String attribute = "";
        while(c > 0) {
            if(c == '\n') {
                System.out.println(attribute);
                String[] sTemp = splitString(attribute, " ", 3);
                switch(sTemp.length) {
                    case 3 : // Adding Nominal
                        String[] sArray = sTemp[2].substring(1, sTemp[2].length()-2).split(",");
                        FastVector attributNominal = new FastVector();
                        for(int i = 0; i < sArray.length; i++) {
                            System.out.println(sArray[i]);
                            attributNominal.addElement(sArray[i]);
                        }
                        atts.addElement(new Attribute(sTemp[1],attributNominal));
                        break;
                    case 2:
                        atts.addElement(new Attribute(sTemp[1]));
                        break;
                    default:
                        break;
                }
                attribute = "";
            }
            c = is.read();
            attribute += (char) c;
        }
        dataInstances = new Instances("DataModel", atts, 280000);
        dataInstances.setClassIndex(dataInstances.numAttributes()-1);
        
        System.out.println(dataInstances.numAttributes());
    }
    /**
     * Simple Load Model
     * @param path File Path Model
     * @return
     */
    public static Classifier LoadModel(String path) {
        try {
            InputStream is = GaIBReviewer_Ali.class.getResourceAsStream(path);
            return (Classifier) weka.core.SerializationHelper.read(is);
        } catch (Exception ex) {
            Logger.getLogger(GaIBReviewer.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    public double submitTransaction(String[] transaction) {
        double[] vals = new double[dataInstances.numAttributes()]; // 4 Atributes
        
        vals[0] = dataInstances.attribute(0).indexOfValue(transaction[1]);
        
        vals[1] = IndexOfRangeInAtribute(dataInstances.attribute(1), Double.parseDouble(transaction[8]));
        
        if(transaction[14].equals("?")) 
            vals[2] = 0.0;
        else
            vals[2] = dataInstances.attribute(2).indexOfValue(transaction[14]);
        
        if(transaction[16].equals("?")) 
            vals[3] = 0.0;
        else
            vals[3] = 1.0;
        
        vals[4] = Instance.missingValue();
        
        Instance data = new Instance(1.0, vals);
        dataInstances.add(data);
        data.setDataset(dataInstances);
        dataInstances.add(data);
        
        double classifyDouble=0.5;
        double[] distribution = null;
        try{
            classifyDouble = cls.classifyInstance(data);
            data.setClassValue(classifyDouble);
            distribution = cls.distributionForInstance(data);
            //System.out.println("Clasifying...");
        } catch (Exception ex) {
            //System.out.println(ex.toString());
            Logger.getLogger(GaIBReviewer.class.getName()).log(Level.SEVERE, null, ex);
        }
        if(distribution != null) {
            for(int i=0; i < distribution.length; i++) {
                System.err.println("Double " + i + " : " + distribution[i]);
            }
        }
        
        System.out.println(dataInstances.attribute(dataInstances.numAttributes()-1).value((int)classifyDouble));
        return (classifyDouble);
    }

    public void submitOutcome(String result) {
        System.out.println(cls.getClass().getName());
        if(cls instanceof UpdateableClassifier) {
            
            for(int i =0; i < dataInstances.numInstances(); i++) {
                Instance instance = dataInstances.instance(i);
                instance.setClassValue(dataInstances.classAttribute().indexOfValue(result));
                try {
                    ((UpdateableClassifier)cls).updateClassifier(instance);
                } catch (Exception ex) {
                    System.out.println(ex.toString());
                }
            }
            
            dataInstances.delete();
            System.out.println("Updateable");
        } else {
            System.out.println("Not Updateable");
        }
    }
    
    /**
     * 
     * @param att Must be atribut involve the range of number
     * @param val
     * @return 
     */
    private double IndexOfRangeInAtribute(Attribute att, double val) {
        double res = 0;
        for(int i=0; i<att.numValues(); i++) {
            String s = att.value(i);
            String[] stemp = s.split("-");
            if(val< Double.parseDouble(stemp[stemp.length-1]))
                break;
            else
                res += 1.0;
        }
        return res;
    }
    
    private String[] splitString(String s, String regex, int nMax) {
        String[] sRes, sTemp = s.split(regex);
        String s_1 = "";
        if(sTemp.length > nMax) {
            sRes = new String[nMax];
            s_1 = sTemp[nMax-1];
            for(int i=nMax; i < sTemp.length; i++) {
                s_1 += " " + sTemp[i];
            }
            for(int i=0; i < nMax-1; i++) {
                sRes[i] = sTemp[i];
            }
            sRes[nMax-1] = s_1;
        } else {
            sRes = sTemp;
        }   
        return sRes;
    }
}
